from IPython.core.display import display, HTML
display(HTML("<style>.container { width: 90% !important; }</style>"))
!pip install tensorflow==1.15.5
!pip install keras==2.3.1
import pandas as pd
import numpy as np
import keras
import pickle
import os
import cv2
import io
import boto3
import tensorflow as tf
import seaborn as sns
from PIL import Image
import matplotlib.pyplot as plt
from matplotlib.image import imread
from sklearn.model_selection import train_test_split
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, MaxPool2D, Flatten
from sklearn.metrics import classification_report, confusion_matrix
from tensorflow.keras.callbacks import EarlyStopping
from IPython.display import Markdown as md
import s3fs
print(tf.__version__)
print(keras.__version__)
bucket_name = 'wongkj11-pda-plants'
conn = boto3.client('s3')
# s3 = boto3.client('s3')
fs = s3fs.S3FileSystem()
list_plant_classes_as_text = []
response = conn.list_objects_v2(Bucket = bucket_name, Prefix='', Delimiter='/')
for content in response.get('CommonPrefixes', []):
plant_dir = content['Prefix'].split('/')[0]
if plant_dir.upper() != '.DS_STORE':
list_plant_classes_as_text.append(plant_dir)
dict_plant_classes = {}
for index, value in enumerate(list_plant_classes_as_text):
if value.upper()!= 'PLANTVILLAGE':
dict_plant_classes.update({ index: value })
# pd.DataFrame.from_dict(dict_plant_classes, orient='index', columns=["PLANT_CLASS"]).to_csv("plant_classes.csv")
def convert_image_to_array(image_loc):
try:
raw = fs.open(f'{image_loc}').read()
if raw is None:
return np.array([])
else:
np_image = cv2.imdecode(np.asarray(bytearray(raw)), cv2.IMREAD_COLOR)
np_image_resize = cv2.resize(np_image, (256, 256))
return np_image_resize
except Exception as e:
print(e)
def returnClassInteger(category):
for key, value in dict_plant_classes.items():
if category.upper() == value.upper():
return key
image_array_list, image_location_list, label_list = [], [], []
response = conn.list_objects_v2(Bucket = bucket_name, Prefix='', Delimiter='/')
for content in response.get('CommonPrefixes', []):
plant_dir = content['Prefix'].split('/')[0]
print(f"[PROCESSING]...{plant_dir}")
contents = conn.list_objects(Bucket = bucket_name, Prefix = plant_dir)['Contents']
for img_loc in contents[:150]:
if img_loc['Key'].upper().endswith('.JPG'):
image_array_list.append(convert_image_to_array(f"s3://{bucket_name}/{img_loc['Key']}"))
image_location_list.append(f"{img_loc['Key']}")
label_list.append(returnClassInteger(plant_dir))
print(f"[COMPLETE]...")
# Pickling the Image Locaiton List
# with open("image_location_list.txt", "wb") as fp: #Pickling
# pickle.dump(image_location_list, fp)
# Unpickling the Image Location List
# with open("image_location_list.txt", "rb") as fp: # Unpickling
# image_location_list = pickle.load(fp)
np_features = np.c_[image_array_list].astype(np.uint8)
np_labels = np.c_[label_list].astype(np.uint8)
x_train, x_test, y_train, y_test = train_test_split(np_features, np_labels, test_size = 0.2, random_state = 42)
x_train_norm = x_train/255
x_test_norm = x_test/255
y_cat_train = to_categorical(y_train, len(dict_plant_classes))
y_cat_test = to_categorical(y_test, len(dict_plant_classes))
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(3,3), padding="VALID", strides=(1, 1), input_shape=(256,256,3), activation='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Conv2D(filters=32, kernel_size=(3,3), padding="VALID", strides=(1, 1), input_shape=(256,256,3), activation='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dense(len(dict_plant_classes), activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics = ['accuracy'])
model.summary()
early_stop = EarlyStopping(monitor='val_loss', patience = 2)
model.fit(x_train_norm, y_cat_train, epochs = 15, validation_data = (x_test_norm, y_cat_test), callbacks = [early_stop])
model.history.history
pd.DataFrame.from_dict(model.history.history, orient='index',
columns=["EPOCH_1","EPOCH_2","EPOCH_3","EPOCH_4","EPOCH_5","EPOCH_6"])
metrics = pd.DataFrame(model.history.history)
metrics
metrics[['acc','val_acc']].plot();
metrics[['loss','val_loss']].plot();
model.evaluate(x_test_norm, y_cat_test)
predictions = model.predict_classes(x_test_norm)
print(classification_report(y_test, predictions))
print(f'Total Images: {len(image_location_list)}\n')
img_loc = image_location_list[8659]
print(f'Full Image Filepath: {img_loc}\n')
md(f"<h3>[ACTUAL CATEGORY]: {img_loc.split('/')[0]}</h1>")
my_image = convert_image_to_array(f"s3://{bucket_name}/{img_loc}")
plt.imshow(my_image);
predicted_value = model.predict_classes(my_image.reshape(1,256,256,3))[0]
cat_labels_df = pd.DataFrame(dict_plant_classes.items(), columns=['Predicted_Value', 'Category'])
predicted_class = cat_labels_df.loc[cat_labels_df.Predicted_Value == predicted_value, 'Category'].iloc[0]
md(f"<h3>[PREDICTED CATEGORY]: {predicted_class} ({predicted_value})</h1>")
cat_labels_styled = pd.DataFrame(dict_plant_classes.items(), columns=['Predicted_Value', 'Category']).style.hide_index()
model.save_weights(f"pda_weights_150.h5")
# Save Neural Network structure to JSON (no weights)
model_json = model.to_json()
with open('pda_model_150.json', "w") as json_file:
json_file.write(model_json)
num_of_images = '150'
pda_model_name = f'pda_model_{num_of_images}.json'
pda_weights_name = f'pda_weights_{num_of_images}.h5'
import boto3
import re
from sagemaker import get_execution_role
import keras
from keras.models import model_from_json
role = get_execution_role()
# !mkdir keras_model
!mv pda_model_150.json keras_model
!mv pda_weights_150.h5 keras_model
!ls keras_model
import tensorflow as tf
json_file = open('/home/ec2-user/SageMaker/TF1_PROJ/keras_model/' + pda_model_name, 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json, custom_objects={"GlorotUniform": tf.keras.initializers.glorot_uniform})
loaded_model.load_weights(f'/home/ec2-user/SageMaker/TF1_PROJ/keras_model/{pda_weights_name}')
print("loaded model from disk")
from tensorflow.python.saved_model import builder
from tensorflow.python.saved_model.signature_def_utils import predict_signature_def
from tensorflow.python.saved_model import tag_constants
model_version = '1'
export_dir = 'export/Servo/' + model_version
import shutil
shutil.rmtree(export_dir)
build = builder.SavedModelBuilder(export_dir)
tf.compat.v1.disable_eager_execution()
signature = predict_signature_def(inputs = {"inputs": loaded_model.input}, outputs = {"score": loaded_model.output})
from keras import backend as K
with K.get_session() as sess:
build.add_meta_graph_and_variables(
sess = sess, tags = [tag_constants.SERVING], signature_def_map = {"serving_default": signature}
)
build.save()
!ls export/Servo/1/variables
import tarfile
with tarfile.open(f'model_{num_of_images}.tar.gz', mode = 'w:gz') as archive:
archive.add('export', recursive = True)
import sagemaker
sagemaker_session = sagemaker.Session()
inputs = sagemaker_session.upload_data(path = f'model_{num_of_images}.tar.gz', key_prefix = 'model')
print(f"Bucket name is: {sagemaker_session.default_bucket()}")
# Create empty train.py file
!touch train.py
from sagemaker.tensorflow.model import TensorFlowModel
sagemaker_model = TensorFlowModel(model_data = 's3://' + sagemaker_session.default_bucket() + f'/model/model_{num_of_images}.tar.gz', role = role, framework_version = '1.15', entry_point = 'train.py')
This step can take up to ~10 minutes
%%time
# Deploy a SageMaker to an endpoint
predictor = sagemaker_model.deploy(initial_instance_count = 1, instance_type = 'ml.m4.xlarge')
print(f"Our Enpoint is called: {predictor.endpoint}")
from sagemaker.tensorflow.serving import Predictor
predictor = Predictor(endpoint_name = "tensorflow-inference-2021-08-19-01-58-58-303")
import cv2
import numpy as np
img_loc = image_location_list[98]
bucket_name = 'wongkj11-pda-plants'
full_image_path = f"s3://{bucket_name}/{img_loc}"
full_image_path
headers = {"content-type": "application/json"}
raw = fs.open(f'{full_image_path}').read()
raw
np_image = cv2.imdecode(np.asarray(bytearray(raw)), cv2.IMREAD_COLOR)
image_content = np_image.astype('uint8').tolist()
body = {"instances": [{"inputs": image_content}]}
try:
results = predictor.predict(body)
print(results)
except Exception as e:
print(e)
def returnClassInteger(num):
for key, value in dict_plant_classes.items():
if num == key:
return value
df = pd.DataFrame(results['predictions'][0], columns=['classes'])
category = int(df.loc[df.classes == 1, :].index[0])
print(f"Category = {returnClassInteger(category)}, {category}")
dict_plant_classes
from PIL import Image
import io
import base64
import matplotlib.image as mpimg
image_resized = Image.open(io.BytesIO(raw)).resize((256, 256), Image.ANTIALIAS)
image_resized
fp = io.BytesIO(bytearray(raw))
fp
mpimg.imread(fp, format = "jpeg")[:,:,::-1]
image_name = "river-pic.jpeg"
# Image.open(f'{image_name}').resize((256, 256), Image.ANTIALIAS)
image_orig = Image.open(f'{image_name}')
image_orig
in_mem_file = io.BytesIO()
image_orig.save(in_mem_file, format = "JPEG")
in_mem_file.getValue()
mpimg.imread(in_mem_file, format = "jpeg")[:,:,::-1]
conn.upload_fileobj(
in_mem_file, # This is what i am trying to upload
"wongkj11-pda-image-upload",
"new-plant-image.jpeg"
)
image_resized
mpimg.imread(fp, format = "jpeg")[:,:,::-1]
with open(image_name, "rb") as image:
img_file = image.read()
img_byte = bytearray(img_file)
# From here
img_resized = Image.open(io.BytesIO(img_byte)).resize((256, 256), Image.ANTIALIAS)
in_mem_file = io.BytesIO()
img_resized.save(in_mem_file, format = "JPEG")
print(in_mem_file.getvalue())
img_resized
in_mem_file.read()
in_mem_file.read()
base64.b64decode(image_resized)
fp = io.BytesIO(bytearray(in_mem_file.read()))
fp
mpimg.imread(in_mem_file, format = "jpeg")[:,:,::-1]
fs.open("x_river-pic.jpeg").read()